-- Bine
-- Create by panyl
-- 魔藤对象

Bine = {
    classId = 0,
    hp     = 0,
    mp     = 0,
    level  = 0,
    skills  = {},

    -- 对象类型为魔藤
    type = OBJECT_TYPE_BINE,
};
Bine.__index = Bine;

-- 构造函数
function Bine.new(classId, data)
    local self = {};
    setmetatable(self, Bine);
    self.classId = classId;
    self.dbase = Dbase.new(data);

    for key, value in pairs(data) do
        self[key] = value;
    end

    -- 设置魔藤的数据
    if data.level ~= nil then
        self.level = data.level
    end

    -- 如果有技能
    if data.skills ~= nil then
        self:setSkills(data.skills);
    else
        self:setSkills({});
    end

    -- 客户端需要设置下hp、mp，因为刚刚种植时是有没有这两项属性的
    self.dbase:set("hp", self:query("hp"));
    self.dbase:set("mp", self:query("mp"));

    return self;
end

-- 取得该对象的描述字符串
function Bine:get_ob_id()
    return string.format("Bine:%s", tostring(self.classId));
end

-- 查找数据
function Bine:query(path, path2, default)
    local value = self.dbase:query(path, path2, default);
    if value then
        return value;
    end

    if path == "classId" or path == "class_id" then
        return self.classId;
    elseif path == "level"  then return self.level;
    elseif path == "hp" then
        return FormulaM.invoke("BINE_BASE_HP", self:getLevel());
    elseif path == "mp" then
        return FormulaM.invoke("BINE_BASE_MP", self:getLevel());
    elseif path == "max_hp" then
        return FormulaM.invoke("CALC_BINE_MAX_HP", self);
    elseif path == "max_mp" then
        return FormulaM.invoke("CALC_BINE_MAX_MP", self);
    elseif path == "attack" then
        return FormulaM.invoke("CALC_BINE_ATTACK", self);
    elseif path == "magic" then
        return FormulaM.invoke("CALC_BINE_MAGIC", self);
    else
        return BineM.query(self.classId, path);
    end
end

-- 设置血量
function Bine:setHp(hp)
    local add = hp - self:getHp(false);
    local baseHp = self.dbase:query("hp", 0) + add;

    self.dbase:set("hp", baseHp);

    BineM.syncBineData();
end

-- 设置魔法值
function Bine:setMp(mp)
    local add = mp - self:getMp(false);
    local baseMp = self.dbase:query("mp", 0) + add;

    self.dbase:set("mp", baseMp);

    BineM.syncBineData();
end

-- 魔藤后天技能
function Bine:getSkills()
    -- 所有后天学习的技能
    return self.skills;
end

-- 魔藤所有技能
function Bine:getAllSkills()
    return self:getSkills();
end

-- 查询属性
function Bine:queryAttrib(attrib, args)
    return AttribM.queryAttrib(self, attrib, args);
end

-- 计算最大血量
function Bine:getMaxHp()
    return FormulaM.invoke("CALC_BINE_MAX_HP", self);
end

-- 当前血量
function Bine:getHp(fix)
    if fix == nil then
        -- 默认需要修正
        fix = true;
    end

    return FormulaM.invoke("CALC_BINE_HP", self, fix);
end

-- 获取魔法值
function Bine:getMp(fix)
    if fix == nil then
        -- 默认需要修正
        fix = true;
    end

    return FormulaM.invoke("CALC_BINE_MP", self, fix);
end

-- 获取最大魔法值
function Bine:getMaxMp()
    return FormulaM.invoke("CALC_BINE_MAX_MP", self);
end

-- 计算基础攻击值
function Bine:getAttack()
    return FormulaM.invoke("CALC_BINE_ATTACK", self);
end

-- 计算基础魔法值
function Bine:getMagic()
    return FormulaM.invoke("CALC_BINE_MAGIC", self);
end

-- 命中
function Bine:getAccuracy()
    -- 暂时用玩家的命中
    return FormulaM.invoke("CALC_USER_ACCURACY", ME.user);
end

-- 闪避
function Bine:getDodge()
    -- 暂时用玩家的闪避
    return FormulaM.invoke("CALC_USER_DODGE", ME.user);
end

-- 获取等级
function Bine:getLevel()
    return self.level or 0;
end

-- 名称
function Bine:getName()
    return self:query("name");
end

-- 获取属主
function Bine:getOwner()
    -- TODO
    return self.pos;
end

function Bine:getPos()
    return self:getOwner();
end

-- 受到伤害
function Bine:receiveDamage(damage)
    local hp = self.dbase:query("hp", 0) - damage;

    self.dbase:set("hp", hp);

    BineM.syncBineData();

    local msg = string.format("[Bine]%s收到伤害：%d，当前hp：%d，max_hp：%d",
        self:getName(), damage, self:getHp(false), self:getMaxHp());
    DungeonLogM.addLog(msg);

    -- 抛出魔藤受创事件
    EventMgr.fire(event.BINE_DAMAGED, {["bine"] = self, ["damage"] = damage, });

    return hp;
end

-- 死亡
function Bine:die()
    if self:getHp() > 0 then
        return false;
    end

    --[[ SLIMED-973,魔藤死亡时，保留光环效果
    -- 这里调整一下加成值
    local bineAddon = ME.user.dbase:query("bine_addon");
    if type(bineAddon) == "table" then
        bineAddon["attack"] = 0;
        bineAddon["magic"]  = 0;

        -- 需要特殊处理一下，以免玩家挂掉
        local v = bineAddon["max_hp"] - ME.user:getHp() + 1;
        bineAddon["max_hp"] = math.max(0, v);

        -- 魔法值
        v = bineAddon["max_mp"] - ME.user:getMp() + 1;
        bineAddon["max_mp"] = math.max(0, v);

        -- 标记属性全部脏了
        AttribM.setAllDirty(ME.user, true);

        EventMgr.fire(event.USER_INFO_UPDATED, "bine_addon");
    end
    ]]
    DungeonLogM.addLog("[Bine]魔藤死亡了。");

    -- 标记死亡
    self.dbase:set("is_dead", 1);

    BineM.syncBineData();

    -- 抛出事件
    EventMgr.fire(event.BINE_DIE);

    return true;
end

-- 是否已死亡
function Bine:isDead()
    -- 有死亡标志
    if 1 == self.dbase:query("is_dead") then
        return true;
    end

    return false;
end

-- 复活
function Bine:revive(hp, mp)
    self:setHp(hp);
    self:setMp(mp);

    self.dbase:delete("is_dead");

    -- 刷新下属性
    PropM.refresh(self);

    DungeonLogM.addLog("魔藤复活了。");
end

-- 魔藤是否有技能
function Bine:ownSkill(skillId)
    local base = SkillM.findBaseSkill(skillId);
    for _, id in pairs(self.skills) do
        if SkillM.findBaseSkill(id) == base then
            return true;
        end
    end
    return false;
end

-- 技能等级
function Bine:getSkillLevel(skillId)
    local base = SkillM.findBaseSkill(skillId);
    for _, id in pairs(self.skills) do
        if SkillM.findBaseSkill(id) == base then
            return SkillM.query(id, "level");
        end
    end

    return 0;
end

-- 设置等级
function Bine:setLevel(level)
    self.level = level;
end

-- 设置技能
function Bine:setSkills(skills)
    self.skills = skills;
end

-- 升级技能，这里不做检查
function Bine:upgradeSkill(skillId)
    local base = SkillM.findBaseSkill(skillId);
    for index, id in pairs(self.skills) do
        if SkillM.findBaseSkill(id) == base then
            local next = SkillM.query(id, "next");
            self.skills[index] = next;

            break;
        end
    end
end

-- 学习技能
function Bine:learnSkill(skillId)
    table.insert(self.skills, skillId);
end

-- 获取数据
function Bine:getSaveData()
    local ret = {
        ["class_id"] = self.classId,
        ["level"]    = self.level,
        ["action"]   = self.action,
        ["hp"]       = self.dbase:query("hp"),
        ["mp"]       = self.dbase:query("mp"),
        ["is_dead"]  = self.dbase:query("is_dead"),
    };

    local skills = self:getAllSkills();
    if #skills > 0 then
        ret["skills"] = self:getAllSkills();
    end

    return ret;
end
